<template>
    <div
        class="page_root"
        :key="queryUpdateFlag"
        data-page-name="产研项目需求管理（一级）"
        data-page-identification="t_276yzjjl9x"
    >
        <a-spin :spinning="pageLoading.loading" :tip="pageLoading.tip">
            <a-modal
                title="描述"
                width="800px"
                v-model:visible="state.descriptionVisible"
                centered
                :mask-closable="false"
                :keyboard="false"
                @ok="handleSubmitDescription"
                @cancel="cancelDescription"
                :ok-button-props="{ loading: state.descriptionLoading }"
            >
                <div class="description">
                    <QuillEditor
                        v-model:content="state.descriptionModalForm.description"
                        ref="descriptionQuillEditor"
                        :options="editorOption"
                        class="quill-editor"
                    />
                </div>
            </a-modal>
            <!--            转化需求-->
            <a-modal
                v-model:visible="state.modalVisible"
                title="转化为用户故事"
                centered
                :mask-closable="false"
                :keyboard="false"
                destroy-on-close
                :body-style="{
                    maxHeight: '800px',
                    overflowY: 'auto'
                }"
                width="1000px"
                @cancel="cancelStory"
                @ok="storyConfirmMbTask"
                :ok-button-props="{ loading: state.okLoading }"
            >
                <div class="form-model">
                    <a-form :model="state.modalForm" ref="storyFormRef" :rules="storyRules">
                        <a-row>
                            <a-col :span="12">
                                <a-form-item label="月份">
                                    <a-date-picker
                                        v-model:value="state.modalForm.monthlyGoalTargetMonth"
                                        value-format="YYYY-MM"
                                        picker="month"
                                        style="width: 100%"
                                        @change="state.modalForm.projectMonthlyGoalManagementId = undefined"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="12">
                                <a-form-item label="月度子目标">
                                    <a-select
                                        :options="state.targetList"
                                        v-model:value="state.modalForm.projectMonthlyGoalManagementId"
                                        show-search
                                        :filterOption="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                                        allow-clear
                                        @focus="getTarget"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="24">
                                <a-form-item label="迭代项目" name="projectId">
                                    <a-tree-select
                                        show-search
                                        style="width: 100%"
                                        placeholder="请选择"
                                        allow-clear
                                        treeDefaultExpandAll
                                        :fieldNames="{
                                            children: 'children',
                                            label: 'projectName',
                                            value: 'projectId',
                                            key: 'projectId'
                                        }"
                                        v-model:value="state.modalForm.projectId"
                                        :tree-data="state.projectTreeDate"
                                    />
                                </a-form-item>
                            </a-col>

                            <a-col :span="12">
                                <a-form-item label="需求编号">
                                    <a-select
                                        v-model:value="state.modalForm.number"
                                        placeholder="请选择"
                                        allowClear
                                        mode="multiple"
                                        show-search
                                        :filter-option="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="12">
                                <a-form-item label="标签" name="labels">
                                    <a-input
                                        v-model:value="state.modalForm.labels"
                                        show-count
                                        :placeholder="inputHolder"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="12">
                                <a-form-item label="版本号" name="iterationVersionId">
                                    <a-select
                                        v-model:value="state.modalForm.iterationVersionId"
                                        placeholder="请选择"
                                        allowClear
                                        :options="state.versionList"
                                        show-search
                                        :filter-option="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="12">
                                <a-form-item label="负责人" name="ownerList">
                                    <a-select
                                        v-model:value="state.modalForm.ownerList"
                                        placeholder="请选择"
                                        allowClear
                                        mode="multiple"
                                        :options="peopleList"
                                        show-search
                                        :filter-option="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="24">
                                <a-form-item label="用户故事名称" name="storyName">
                                    <a-input
                                        v-model:value="state.modalForm.storyName"
                                        :placeholder="inputHolder"
                                        maxlength="100"
                                        show-count
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="12">
                                <a-form-item label="计划起止时间">
                                    <a-range-picker
                                        style="width: 100%"
                                        v-model:value="state.modalForm.timeRangeList"
                                        valueFormat="YYYY-MM-DD"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="12">
                                <a-form-item
                                    label="优先级"
                                    name="priority"
                                    :rules="[{ required: true, message: '请选择优先级', trigger: 'blur' }]"
                                >
                                    <a-select :options="state.priorityList" v-model:value="state.modalForm.priority" />
                                </a-form-item>
                            </a-col>
                            <a-col :span="24">
                                <a-form-item label="描述">
                                    <QuillEditor
                                        v-model:content="state.modalForm.description"
                                        ref="storyQuillEditor"
                                        :options="editorOption"
                                        class="quill-editor"
                                    />
                                </a-form-item>
                            </a-col>
                        </a-row>
                    </a-form>
                </div>
            </a-modal>
            <!--            转化需求-->
            <!--          关联需求-->
            <a-modal
                v-model:visible="state.correlationVisible"
                title="关联用户故事"
                centered
                :mask-closable="false"
                :keyboard="false"
                destroy-on-close
                :body-style="{
                    maxHeight: '800px',
                    overflowY: 'auto'
                }"
                @cancel="cancelCorrelation"
                @ok="handleSubmitCorrelation"
                :ok-button-props="{ loading: state.correlationLoading }"
            >
                <div class="form-model">
                    <a-form :model="state.correlationForm" ref="correlationRef">
                        <a-row>
                            <a-col :span="24">
                                <a-form-item
                                    label="迭代项目"
                                    name="projectId"
                                    :rules="{ required: true, message: '请选择迭代项目!' }"
                                >
                                    <a-tree-select
                                        show-search
                                        style="width: 100%"
                                        placeholder="请选择"
                                        allow-clear
                                        treeDefaultExpandAll
                                        :fieldNames="{
                                            children: 'children',
                                            label: 'projectName',
                                            value: 'projectId',
                                            key: 'projectId'
                                        }"
                                        v-model:value="state.correlationForm.projectId"
                                        :tree-data="state.projectTreeDate"
                                    />
                                </a-form-item>
                            </a-col>

                            <a-col :span="24">
                                <a-form-item
                                    label="用户故事"
                                    name="storyId"
                                    :rules="{ required: true, message: '请选择用户故事!' }"
                                >
                                    <a-select
                                        :placeholder="selectHolder"
                                        v-model:value="state.correlationForm.storyId"
                                        showSearch
                                        :options="state.storyList"
                                        :field-names="{ label: 'label', value: 'value' }"
                                        :filter-option="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                                        @focus="getStory"
                                    />
                                </a-form-item>
                            </a-col>
                        </a-row>
                    </a-form>
                </div>
            </a-modal>
            <!--          关联需求-->
            <!-- begin vid_g7h6qu0cw2 自定义模板_cpcn9v6xu5 -->
            <div class="required-management">
                <div class="top-search">
                    <!-- 第一行筛选条件 -->
                    <a-row :gutter="16">
                        <a-col :span="6">
                            <a-form-item label="关键字" :label-col="{ span: 5 }" :wrapper-col="{ span: 19 }">
                                <a-input v-model:value="state.searchForm.overview" :placeholder="inputHolder" />
                            </a-form-item>
                        </a-col>
                        <a-col :span="6">
                            <a-form-item label="状态" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
                                <a-select
                                    v-model:value="state.searchForm.status"
                                    placeholder="请选择"
                                    allowClear
                                    :options="state.statusList"
                                    show-search
                                    :filter-option="
                                        (input, option) => {
                                            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                        }
                                    "
                                />
                            </a-form-item>
                        </a-col>
                        <a-col :span="6">
                            <a-form-item label="优先级" :label-col="{ span: 5 }" :wrapper-col="{ span: 19 }">
                                <a-select
                                    v-model:value="state.searchForm.priority"
                                    placeholder="请选择"
                                    allowClear
                                    :options="state.priorityList"
                                    show-search
                                    :filter-option="
                                        (input, option) => {
                                            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                        }
                                    "
                                />
                            </a-form-item>
                        </a-col>
                        <a-col :span="6">
                            <a-form-item label="需求提出人" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
                                <a-select
                                    :placeholder="selectHolder"
                                    v-model:value="state.searchForm.proposer"
                                    showSearch
                                    :options="peopleList"
                                    :field-names="{ label: 'label', value: 'value' }"
                                    :filter-option="
                                        (input, option) => {
                                            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                        }
                                    "
                                    @focus="getAllJfPeople"
                                />
                            </a-form-item>
                        </a-col>
                        <a-col :span="6">
                            <a-form-item label="责任人" :label-col="{ span: 5 }" :wrapper-col="{ span: 19 }">
                                <a-select
                                    :placeholder="selectHolder"
                                    v-model:value="state.searchForm.owner"
                                    showSearch
                                    :options="peopleList"
                                    :field-names="{ label: 'label', value: 'value' }"
                                    :filter-option="
                                        (input, option) => {
                                            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                        }
                                    "
                                    @focus="getAllJfPeople"
                                />
                            </a-form-item>
                        </a-col>
                        <a-col :span="6">
                            <a-form-item label="需求提出时间" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
                                <a-range-picker
                                    value-format="YYYY-MM-DD"
                                    :placeholder="selectHolder"
                                    v-model:value="state.searchForm.proposedTimeList"
                                />
                            </a-form-item>
                        </a-col>
                        <a-col :span="12" style="display: flex; align-items: start; justify-content: end">
                            <a-space>
                                <a-button type="primary" @click="getDataResetPagination">查询</a-button>
                                <a-button @click="resetData" type="primary" ghost>重置</a-button>
                            </a-space>
                        </a-col>
                    </a-row>

                    <!-- 操作按钮 -->
                </div>
                <div class="content">
                    <div class="table-top">
                        <div class="top-tip">
                            <!--                          <ExclamationCircleFilled class="tip-img" />-->
                            <!--                            注：该需求池为项目内部需求池，无需解决需求无需录入。请做好需求与用户故事的对应关系，内部需求池仅支持多对一、一对一的需求与用户故事关系-->
                            注：该需求池为项目内部需求池，无需解决需求无需录入。请做好需求与用户故事的对应关系，内部需求池仅支持多对一、一对一的需求与用户故事关系
                        </div>
                        <div class="top-right">
                            <a-form-item
                                label="排序"
                                style="margin: 0"
                                :label-col="{ span: 6 }"
                                :wrapper-col="{ span: 18 }"
                            >
                                <a-select
                                    :placeholder="selectHolder"
                                    style="width: 150px"
                                    :options="state.sortList"
                                    v-model:value="state.searchForm.directionField"
                                    @change="getData"
                                    allow-clear
                                />
                            </a-form-item>
                            <a-button
                                type="primary"
                                :loading="downloadLoading"
                                @click="downTemplate"
                                v-permission="'3000001226_vid_luuzzp51uq'"
                                >下载模板
                            </a-button>
                            <a-upload
                                :show-upload-list="false"
                                :before-upload="handlerUpload"
                                accept=".xlsx,.ppt,.pdf,.PDF, image/*, .docx, .rp, .xls"
                            >
                                <a-button v-permission="'3000001226_vid_p5t4paf6pv'">
                                    <upload-outlined />
                                    导入
                                </a-button>
                            </a-upload>
                            <a-button
                                type="primary"
                                @click="handleShowtranmation"
                                v-permission="'3000001226_vid_xdm30xk9ol'"
                                >转化
                            </a-button>
                            <a-button type="primary" v-permission="'3000001226_vid_68a20ilimk'" @click="addRow"
                                >新建
                            </a-button>
                        </div>
                    </div>
                    <div class="table-box">
                        <a-table
                            centered
                            bordered
                            row-key="requirementId"
                            :columns="columns"
                            :data-source="state.dataSource"
                            :scroll="{ y: state.tableHeight }"
                            :loading="state.tableLoading"
                            :row-selection="{
                                selectedRowKeys: state.selectedRowKeys,
                                onChange: onSelectChange,
                                getCheckboxProps: getCheckboxProps
                            }"
                            @resizeColumn="handleResizeColumn"
                            :pagination="pagination"
                            @change="handleTableChange"
                        >
                            <template #bodyCell="{ record, text, column, index }">
                                <!-- 编辑模式 -->
                                <template v-if="record.editable">
                                    <template v-if="column.dataIndex === 'labels'">
                                        <a-input
                                            style="width: 90%"
                                            v-model:value="record.labels"
                                            placeholder="请输入，以‘;’分割"
                                        />
                                    </template>
                                    <template v-else-if="column.dataIndex === 'firstModule'">
                                        <a-input
                                            style="width: 90%"
                                            v-model:value="record.firstModule"
                                            placeholder="请输入"
                                        />
                                    </template>
                                    <template v-else-if="column.dataIndex === 'secondModule'">
                                        <a-input
                                            style="width: 90%"
                                            v-model:value="record.secondModule"
                                            placeholder="请输入"
                                        />
                                    </template>
                                    <template v-else-if="column.dataIndex === 'status'">
                                        <a-select
                                            style="width: 90%"
                                            v-model:value="record.status"
                                            placeholder="请选择"
                                            allowClear
                                            :options="state.addStatusList"
                                            show-search
                                            :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                                        />
                                    </template>
                                    <template v-else-if="column.dataIndex === 'iterationVersionName'">
                                        <a-select
                                            style="width: 90%"
                                            v-model:value="record.iterationVersionId"
                                            placeholder="请选择"
                                            allowClear
                                            :disabled="record.storyId"
                                            :options="state.editVersionList"
                                            show-search
                                            :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                                        />
                                    </template>
                                    <template v-else-if="column.dataIndex === 'owner'">
                                        <a-select
                                            style="width: 100%"
                                            :placeholder="selectHolder"
                                            v-model:value="record.owner"
                                            showSearch
                                            :options="peopleList"
                                            :field-names="{ label: 'label', value: 'value' }"
                                            :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                                            @focus="getAllJfPeople"
                                        />
                                    </template>
                                    <template v-else-if="column.dataIndex === 'overview'">
                                        <a-input
                                            style="width: 90%"
                                            v-model:value="record.overview"
                                            :placeholder="inputHolder"
                                        />
                                    </template>

                                    <template v-else-if="column.dataIndex === 'priority'">
                                        <a-select
                                            style="width: 90%"
                                            v-model:value="record.priority"
                                            :options="state.priorityList"
                                        />
                                    </template>

                                    <template v-else-if="column.dataIndex === 'proposer'">
                                        <a-select
                                            style="width: 100%"
                                            :placeholder="selectHolder"
                                            v-model:value="record.proposer"
                                            showSearch
                                            :options="peopleList"
                                            :field-names="{ label: 'label', value: 'value' }"
                                            :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                                            @focus="getAllJfPeople"
                                        />
                                    </template>

                                    <template v-else-if="column.dataIndex === 'proposedTime'">
                                        <a-date-picker
                                            v-model:value="record.proposedTime"
                                            format="YYYY-MM-DD"
                                            value-format="YYYY-MM-DD"
                                            style="width: 100%"
                                        />
                                    </template>

                                    <template
                                        v-else-if="
                                            ['designStartTime', 'designEndTime', 'reviewFinishTime'].includes(
                                                column.dataIndex
                                            )
                                        "
                                    >
                                        <a-date-picker
                                            v-model:value="record[column.dataIndex]"
                                            format="YYYY-MM-DD"
                                            value-format="YYYY-MM-DD"
                                            style="width: 100%"
                                        />
                                    </template>

                                    <template v-else>
                                        <span>{{ record[column.dataIndex] }}</span>
                                    </template>
                                </template>

                                <!-- 非编辑模式 -->
                                <template v-else>
                                    <template v-if="column.dataIndex === 'priority'">
                                        <div
                                            class="priority-tag"
                                            title="优先级"
                                            :style="{ backgroundColor: getBgc(record.priority) }"
                                            >{{ record.priority || 'NO' }}
                                        </div>
                                    </template>
                                    <template v-if="column.dataIndex === 'status'">
                                        <div class="edit-approve">
                                            <div
                                                class="status-tag"
                                                title="任务状态"
                                                :style="{
                                                    backgroundColor: getStatusColor(record.status)
                                                }"
                                                >{{ record.status || '暂无' }}
                                            </div>
                                        </div>
                                    </template>
                                </template>

                                <template v-if="column.dataIndex === 'operation'">
                                    <a-space :size="0">
                                        <a-button
                                            type="link"
                                            v-permission="'3000001226_vid_nj72qtz0ab'"
                                            size="small"
                                            v-if="record.storyId"
                                            @click="jumpTask('storyAndTask', record.projectId, record.storyId)"
                                            >查看
                                        </a-button>
                                        <a-button
                                            type="link"
                                            size="small"
                                            v-if="!record.editable"
                                            @click="showDescription(record)"
                                            >描述
                                        </a-button>
                                        <a-button
                                            type="link"
                                            v-if="record.editable"
                                            size="small"
                                            @click="saveRow(record)"
                                            >完成
                                        </a-button>
                                        <a-button
                                            type="link"
                                            size="small"
                                            v-permission="'3000001226_vid_gho71scpe1'"
                                            @click="editRow(record)"
                                            v-if="!record.editable"
                                            >编辑
                                        </a-button>
                                        <a-popconfirm title="确定删除吗?" @confirm="deleteRow(record)" placement="left">
                                            <a-button
                                                v-permission="'3000001226_vid_fqkqfyw9kf'"
                                                type="link"
                                                size="small"
                                                v-if="!record.isNew"
                                                >删除
                                            </a-button>
                                        </a-popconfirm>
                                        <a-button
                                            type="link"
                                            size="small"
                                            v-if="record.isNew"
                                            @click="cancelEdit(record)"
                                            >取消
                                        </a-button>
                                        <a-button
                                            type="link"
                                            size="small"
                                            v-permission="'3000001226_vid_kzqgd5sg6r'"
                                            @click="showCorrelation(record)"
                                            v-if="!record.storyId"
                                            >关联用户故事
                                        </a-button>
                                    </a-space>
                                </template>
                            </template>
                        </a-table>
                    </div>
                </div>
            </div>
            <!-- end vid_g7h6qu0cw2 自定义模板_cpcn9v6xu5 -->
        </a-spin>
    </div>
</template>
<script setup lang="tsx">
    import {
        h,
        ref,
        reactive,
        toRaw,
        markRaw,
        watch,
        computed,
        onBeforeMount,
        onMounted,
        onBeforeUnmount,
        onUnmounted,
        onActivated,
        onDeactivated
    } from 'vue'
    import { useRoute, useRouter } from 'vue-router'

    const router = useRouter()
    const route = useRoute()
    import { get, post, put, del, request, requestWithHeaders } from '@/utils/http/Axios'
    import {
        cloneDeep,
        localGet,
        merge,
        getDifferenceArray,
        traversalTreeStructure,
        checkCaseCondition,
        renderStringInTemplate,
        handleBreadcrumbJump,
        throttle,
        permission,
        getComponentParamsValue
    } from '@/utils/index'
    import { isNullOrEmpty, isEmptyArr, isNullOrUnDef, isContained, isArray, isEmpty, isObject } from '@/utils/is'
    import dayjs from 'dayjs'
    import { getPagePcChartsDataSourceConvert } from '@/utils/chart'
    import { message, notification, Modal } from 'ant-design-vue'
    import {
        propertyFormatByNumber,
        propertyFormatByPercentage,
        propertyFormatByDate,
        parseSubFromDataList
    } from '@/utils/format'
    import colorTheme from '@/design/custom-theme.json'

    /*** PUBLISH_EXEGESIS ***
 import UserTableRecords from '@/model/UserTableRecords';
 import { getAppBaseUrl } from '@/utils/index';
 import { sendToken } from "@/hooks/useIframeToken";
 import { useSystemStore } from "@/store/modules/system";
 const systemStore = useSystemStore();
 *** PUBLISH_EXEGESIS ***/

    // 获取传入的流程ID和组件参数
    const props = defineProps({
        'processInstanceId': {
            type: [String, Number, Boolean],
            default: undefined
        },
        'useProjectId': {
            type: [String, Number],
            default: undefined
        },
        'activeKey': {
            type: [String],
            default: undefined
        },
        'refreshCount': {
            type: [String],
            default: undefined
        }
    })
    const immediateWatch = (source, callback) => {
        watch(source, callback, { deep: true, immediate: true })
    }

    /* -------------------------- 属性定义 -------------------------- */

    const setTimeOutList = []
    const pageLoading = reactive({
        loading: false,
        tip: undefined
    })
    const authInfo = localGet('app-user-store')

    // 处理校验
    const setSubFormName = (parentInfo, name) => {
        return [parentInfo.parents, parentInfo.cycleIndex, name]
    }

    /* ========================== 属性定义 ========================== */

    /* -------------------------- 元素数据引用 -------------------------- */

    /* ========================== 元素数据引用 ========================== */

    /* -------------------------- 页面数据 -------------------------- */

    /* ========================== 页面数据 ========================== */

    /* -------------------------- 响应 -------------------------- */

    /* ========================== 响应 ========================== */

    /* -------------------------- 函数 -------------------------- */

    /* ========================== 函数 ========================== */

    /* -------------------------- 页面参数 -------------------------- */

    const pageParameter_state = reactive({
        'processInstanceId': props.processInstanceId ?? route.query.processInstanceId
    })

    /* ========================== 页面参数 ========================== */

    /* -------------------------- 组件事件处理方法 -------------------------- */

    // ---------------------------- 组件数据同步 ----------------------------

    // ============================ 组件数据同步 ============================

    /* ========================== 组件事件处理方法 ========================== */

    /* -------------------------- 生命周期 -------------------------- */
    // 用于参数变更后重新执行自定义指令
    const queryUpdateFlag = ref(0)
    onMounted(() => {})

    onUnmounted(() => {
        // 销毁定时器
        setTimeOutList.forEach(({ repeat, timer }) => {
            repeat ? clearInterval(timer) : clearTimeout(timer)
        })
    })

    /* ========================== 生命周期 ========================== */

    /* -------------------------- 数据关联处理 -------------------------- */

    /* -------------------------- 表单数据同步 -------------------------- */
    /* ========================== 表单数据同步 ========================== */

    /* ========================== 数据关联处理 ========================== */

    /* -------------------------- 不同组件自定义的处理逻辑 -------------------------- */

    /* ========================== 不同组件自定义的处理逻辑 ========================== */

    // ================================定制化逻辑========================================
    //     富文本设置
    import { nextTick } from 'vue'
    import { QuillEditor, Quill } from '@vueup/vue-quill'
    import ImageUploader from 'quill-image-uploader'
    import '@vueup/vue-quill/dist/vue-quill.snow.css'

    const titleConfig = [
        { Choice: ' .ql-bold', title: '加粗' },
        { Choice: ' .ql-italic', title: '斜体' },
        { Choice: ' .ql-underline', title: '下划线' },
        { Choice: ' .ql-strike', title: '删除线' },
        { Choice: ' .ql-blockquote', title: '块引用' },
        { Choice: ' .ql-code-block', title: '插入代码' },
        { Choice: ' .ql-size', title: '字体大小' },
        { Choice: ' .ql-size', title: '字体大小' },
        { Choice: ' .ql-color', title: '字体颜色' },
        { Choice: ' .ql-background', title: '字体背景颜色' },
        { Choice: ' .ql-list[value="ordered"]', title: '有序列表' },
        { Choice: ' .ql-list[value="bullet"]', title: '无序列表' },
        { Choice: ' .ql-header[value="1"]', title: '1级标题' },
        { Choice: ' .ql-header[value="2"]', title: '2级标题' },
        { Choice: ' .ql-align', title: '对齐方式' },
        { Choice: ' .ql-clean', title: '清除字体格式' },
        { Choice: ' .ql-image', title: '图像' },
        { Choice: ' .ql-size .ql-picker-item[data-value="small"]', title: '小号' },
        { Choice: ' .ql-size .ql-picker-item[data-value="large"]', title: '大号' },
        { Choice: ' .ql-size .ql-picker-item[data-value="huge"]', title: '超大号' },
        { Choice: ' .ql-size .ql-picker-item:nth-child(2)', title: '标准' },
        { Choice: ' .ql-align .ql-picker-item:first-child', title: '居左对齐' },
        { Choice: ' .ql-align .ql-picker-item[data-value="center"]', title: '居中对齐' },
        { Choice: ' .ql-align .ql-picker-item[data-value="right"]', title: '居右对齐' },
        { Choice: ' .ql-align .ql-picker-item[data-value="justify"]', title: '两端对齐' }
    ]
    // 注册图片上传模块
    Quill.register('modules/imageUploader', ImageUploader)

    // 将本地文件转换为URL
    const getLocalImageURL = file => {
        return new Promise(resolve => {
            const reader = new FileReader()
            reader.onload = e => {
                resolve(e.target.result)
            }
            reader.readAsDataURL(file)
        })
    }

    // 表单数据

    // Quill 编辑器选项
    const editorOption = ref({
        modules: {
            // imageUploader: {
            //     upload: async file => {
            //         const localUrl = await getLocalImageURL(file)
            //         return localUrl // 返回本地图片的 URL 进行预览
            //     }
            // },
            toolbar: [
                ['bold', 'italic', 'underline', 'strike'], // 加粗，斜体，下划线，删除线
                ['blockquote', 'code-block'], // 引用，代码块
                [{ header: 1 }, { header: 2 }], // 标题1，标题2
                [{ list: 'ordered' }, { list: 'bullet' }], // 有序列表，无序列表
                [{ size: ['small', false, 'large', 'huge'] }], // 文字大小
                [{ color: [] }, { background: [] }], // 字体颜色，背景颜色
                [{ align: [] }], // 对齐
                ['clean'], // 清除格式
                ['image'] // 链接，图片，视频
            ]
            // ImageUploader: imageHandler
        }
    })
    // 上传API
    const uploadFileAPI = async file => {
        const data = new FormData()
        data.append('file', file)

        return post('/file-storage/api/v1/file/upload', data)
            .then(({ data: { fullUrl } }) => {
                return { data: { fullUrl } }
            })
            .catch(error => {
                console.error('上传图片出错:', error)
                throw error // 抛出错误以供外部处理
            })
    }

    // 将 dataURL 转换为 File 对象的辅助函数
    const dataURLtoFile = (dataurl, filename) => {
        const arr = dataurl.split(',')
        const mime = arr[0].match(/:(.*?);/)[1]
        const bstr = atob(arr[1])
        let n = bstr.length
        const u8arr = new Uint8Array(n)
        while (n--) {
            u8arr[n] = bstr.charCodeAt(n)
        }
        return new File([u8arr], filename, { type: mime })
    }
    const taskLeader = JSON.parse(localStorage.getItem('al__USER_INFO'))
    const pagination = ref({
        current: 1,
        pageSize: 10,
        showSizeChanger: true,
        total: 0,
        pageSizeOptions: ['10', '20', '40', '60', '80', '100'],
        showTotal: total =>
            `共 ${total} 个项目 第 ${pagination.value.current}/${Math.ceil(total / pagination.value.pageSize)}页`
    })
    const selectHolder = '请选择'
    const inputHolder = '请输入'
    const state = reactive({
        tableHeight: 600,
        searchForm: {
            overview: undefined,
            status: undefined,
            priority: undefined,
            proposer: undefined,
            owner: undefined,
            proposedTimeList: [],
            directionField: 'iteration-version-desc'
        },
        allUser: [],
        priorityList: [],
        statusList: [],
        addStatusList: [],
        dataSource: [],
        sortList: [
            {
                label: '版本号正序',
                value: 'iteration-version-asc'
            },
            {
                label: '版本号倒序',
                value: 'iteration-version-desc'
            },

            {
                label: '创建时间正序',
                value: 'created_time-asc'
            },
            {
                label: '创建时间倒序',
                value: 'created_time-desc'
            },

            {
                label: '优先级正序',
                value: 'priority-asc'
            },

            {
                label: '优先级倒序',
                value: 'priority-desc'
            },

            {
                label: '计划开始时间正序',
                value: 'story_start_time-asc'
            },
            {
                label: '计划开始时间倒序',
                value: 'story_start_time-desc'
            },
            {
                label: '计划完成时间正序',
                value: 'story_end_time-asc'
            },
            {
                label: '计划完成时间倒序',
                value: 'story_end_time-desc'
            },
            {
                label: '需求提出人名称正序',
                value: 'proposer-asc'
            },
            {
                label: '需求提出人名称倒序',
                value: 'proposer-desc'
            }
        ],
        selectedRowKeys: [],
        tranVisible: false,
        tranModalForm: {},
        tranLoading: false,
        descriptionVisible: false,
        isEditDescription: true,
        descriptionModalForm: {},
        descriptionLoading: false,
        submitLoading: false,
        modalVisible: false,
        modalForm: {
            storyName: undefined,
            projectId: undefined,
            iterationVersionId: undefined,
            priority: undefined,
            labels: undefined,
            ownerList: [taskLeader.value.name],
            number: [],
            timeRangeList: [],
            taskList: [],
            templateTaskId: [],
            monthlyGoalTargetMonth: undefined,
            projectMonthlyGoalManagementId: undefined,
            remarks: undefined
        },
        targetList: [],
        versionList: [],
        editVersionList: [],
        projectTreeDate: [],
        storyList: [],
        correlationVisible: false,
        correlationForm: { projectId: undefined, storyId: undefined },
        correlationLoading: false
    })

    const headerOffset = ref(250)
    const calcTableHeight = () => {
        state.tableHeight = window.innerHeight - 180 - headerOffset.value
    }
    onMounted(() => {
        calcTableHeight()
        window.addEventListener('resize', calcTableHeight)
        document.addEventListener('click', e => {
            const target = e.target as HTMLElement
            if (target.tagName === 'IMG' && target.classList.contains('previewable-image')) {
                const imgUrl = target.getAttribute('src')
                if (imgUrl) {
                    // 预览逻辑，如弹窗显示 imgUrl
                    previewImage(imgUrl)
                }
            }
        })
    })

    function previewImage(url) {
        const imgWindow = window.open()
        if (imgWindow) {
            imgWindow.document.write(`<img src="${url}" style="max-width:100%"/>`)
        }
    }

    onBeforeUnmount(() => {
        window.removeEventListener('resize', calcTableHeight)
    })
    const peopleList = ref([])

    function getAllJfPeople() {
        get('/solution-ppm/api/v2/built-in-system-ppm/pmgf/get/allUser').then(({ data }) => {
            peopleList.value = data.userDtoList.map(item => {
                return {
                    label: item.name,
                    value: item.name
                }
            })
        })
    }

    function getAllVersion() {
        post('/solution-ppm/api/v2/built-in-system-ppm/iteration_version/list', {
            projectId: props.useProjectId
        }).then(data => {
            state.versionList = data.data.map(item => {
                return {
                    label: item.version,
                    value: item.id,
                    status: item.status // 👈 保留状态
                }
            })
            state.editVersionList = state.versionList.filter(item => item.status === '未发布')
        })
    }

    function getSearchStatus() {
        get('/solution-ppm-basic-data/api/v1/dictionary/search/PTXQ.ZTSX').then(data => {
            state.statusList = data.data.map(item => {
                return {
                    label: item.itemName,
                    value: item.itemName
                }
            })
        })
    }

    function getStatusList() {
        get('/solution-ppm-basic-data/api/v1/dictionary/search/PTXQ.ZT').then(data => {
            state.addStatusList = data.data.map(item => {
                return {
                    label: item.itemName,
                    value: item.itemName
                }
            })
        })
    }

    function getPriorityList() {
        get('/solution-ppm-basic-data/api/v1/dictionary/search/PTXQ.YXJ').then(data => {
            state.priorityList = data.data.map(item => {
                return {
                    label: item.itemName,
                    value: item.itemName
                }
            })
        })
    }

    watch(
        () => [props.useProjectId, props.activeKey, props.refreshCount],
        val => {
            getData()
            getStatusList()
            getSearchStatus()
            getPriorityList()
            getAllVersion()
        },
        { immediate: true }
    )

    function getData() {
        state.tableLoading = true
        post('/solution-ppm/api/v2/built-in-system-ppm/requirement/search', {
            ...state.searchForm,
            menuId: props.useProjectId,
            pageNo: pagination.value.current,
            pageSize: pagination.value.pageSize
        })
            .then(data => {
                if (data.code !== 200) {
                    message.error(data.message)
                    return
                }
                state.dataSource = data.data.dataList
                pagination.value.total = data.data.totalElements
            })
            .finally(() => {
                state.tableLoading = false
            })
    }

    function getDataResetPagination() {
        pagination.value.current = 1
        pagination.value.pageSize = 10
        getData()
    }

    function resetData() {
        pagination.value.current = 1
        pagination.value.pageSize = 10
        state.searchForm = {
            overview: undefined,
            status: undefined,
            priority: undefined,
            proposer: undefined,
            owner: undefined,
            proposedTimeList: [],
            directionField: 'iteration-version-desc'
        }
        getData()
    }

    const columns = ref([
        {
            dataIndex: 'number',
            title: '需求编号',
            ellipsis: true,
            width: 150,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'labels',
            title: '标签',
            ellipsis: true,
            width: 200,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'firstModule',
            title: '一级模块',
            ellipsis: true,
            width: 200,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'secondModule',
            title: '二级模块',
            ellipsis: true,
            width: 200,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'iterationVersionName',
            title: '需求规划版本',
            ellipsis: true,
            width: 200,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'owner',
            title: '责任人',
            ellipsis: true,
            width: 200,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'overview',
            title: '需求概述',
            width: 200,
            ellipsis: true,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'status',
            title: '状态',
            ellipsis: true,
            width: 150,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'priority',
            title: '优先级',
            width: 150,
            ellipsis: true,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'proposer',
            title: '需求提出人',
            width: 120,
            ellipsis: true,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'proposedTime',
            title: '提出时间',
            ellipsis: true,
            width: 150,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'designStartTime',
            title: '设计开始时间',
            ellipsis: true,
            width: 150,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'designEndTime',
            title: '设计结束时间',
            ellipsis: true,
            width: 150,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'reviewFinishTime',
            title: '评审完成时间',
            ellipsis: true,
            width: 150,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'storyStartTime',
            title: '计划开始时间',
            ellipsis: true,
            width: 150,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'storyEndTime',
            title: '计划完成时间',
            ellipsis: true,
            width: 150,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'operation',
            title: '操作',
            ellipsis: true,
            align: 'center',
            width: 300,
            fixed: 'right',
            resizable: true
        }
    ])

    function handleResizeColumn(w, col) {
        col.width = w
    }

    const handleTableChange = (paginationInfo, filters, sorter) => {
        pagination.value.current = paginationInfo.current
        pagination.value.pageSize = paginationInfo.pageSize
        getData()
    }

    // 新建需求（本地假数据）
    const addRow = () => {
        let name = taskLeader.value.name
        const newRow = {
            id: `tmp_${Date.now()}`,
            labels: undefined,
            description: '',
            status: undefined,
            priority: undefined,
            proposer: name,
            proposedTime: dayjs().format('YYYY-MM-DD'),
            designStartTime: undefined,
            designEndTime: undefined,
            reviewFinishTime: undefined,
            storyStartTime: undefined,
            storyEndTime: undefined,
            editable: true,
            isNew: true // ✅ 标识假数据
        }
        state.dataSource.unshift(newRow)
    }

    // 编辑行
    const editRow = record => {
        record.editable = true
    }

    // 保存行
    const saveRow = async record => {
        if (!record.iterationVersionId) {
            message.info('请选择需求规划版本')
            return
        }
        try {
            let res
            if (record.isNew) {
                // 新建
                res = await post('/solution-ppm/api/v2/built-in-system-ppm/requirement', {
                    ...record,
                    menuId: props.useProjectId
                })
            } else {
                // 编辑
                res = await put('/solution-ppm/api/v2/built-in-system-ppm/requirement', {
                    ...record,
                    menuId: props.useProjectId
                })
            }

            // 接口返回校验
            if (res.code !== 200) {
                message.error(res.message || '保存失败')
                return
            }

            // 更新行数据（用返回值覆盖，取消编辑状态）
            Object.assign(record, res.data || {}, { editable: false, isNew: false })

            message.success(res.message || '保存成功')
        } catch (e) {
            console.error(e)
            message.error('保存失败，请重试')
        }
    }

    // 取消编辑
    const cancelEdit = record => {
        // 新建未保存直接删除
        state.dataSource = state.dataSource.filter(i => i.requirementId !== record.requirementId)
    }

    // 删除行
    const deleteRow = async record => {
        if (record.isNew) {
            state.dataSource = state.dataSource.filter(i => i.requirementId !== record.requirementId)
            return message.success('删除成功（本地）')
        }
        try {
            del(`/solution-ppm/api/v2/built-in-system-ppm/requirement/${record.requirementId}`).then(data => {
                if (data.code !== 200) {
                    message.error(data.message)
                    return
                }
                state.dataSource = state.dataSource.filter(i => i.requirementId !== record.requirementId)
                message.success(data.message)
            })
        } catch {
            message.error('删除失败')
        }
    }

    function handleShowtranmation() {
        if (!props.useProjectId) {
            message.info('请选择项目')
            return
        }
        if (state.selectedRowKeys.length == 0) {
            message.info('请选择需要转化的数据')
            return
        }
        getProjectTreeList()
        state.modalVisible = true

        currentStoryData.value = {}

        // 根据选中的 id 找出对应需求
        const selectedRows = state.dataSource.filter(item => state.selectedRowKeys.includes(item.requirementId))

        // ====== 1️⃣ 用户故事名称（仅选中一条时） ======
        if (selectedRows.length === 1) {
            state.modalForm.storyName = selectedRows[0].overview || ''
            state.modalForm.priority = selectedRows[0].priority || ''
            state.modalForm.ownerList = selectedRows[0].owner
        } else {
            state.modalForm.storyName = ''
        }

        // ====== 2️⃣ 收集需求编号 ======
        const codes = selectedRows.map(item => item.number).filter(Boolean)
        state.modalForm.number = codes

        // ====== 3️⃣ 合并标签（去重 + 分号分隔） ======
        const allTags = selectedRows
            .flatMap(item =>
                typeof item.labels === 'string'
                    ? item.labels.split(/[,;；]/)
                    : Array.isArray(item.labels)
                    ? item.labels
                    : []
            )
            .map(tag => tag.trim())
            .filter(tag => tag)

        const uniqueTags = Array.from(new Set(allTags))
        state.modalForm.labels = uniqueTags.join('；')
    }

    //     获取项目树
    async function getProjectTreeList() {
        await post('/solution-ppm/api/v2/built-in-system-ppm/v2/platform/project/tree', {
            projectName: state.treeSearchName
        }).then(data => {
            if (data.code !== 200) {
                message.error(data.message)
                return false
            }
            // 接口返回的完整项目树
            const tree = data.data
            const parent = findNodeById(tree, props.useProjectId)

            if (parent) {
                console.log('遭到了')
                const siblings = parent.children.filter(c => c.projectId !== props.useProjectId)
                // 这里包装一层父节点，结构清晰
                state.projectTreeDate = [
                    {
                        projectId: parent.projectId,
                        projectName: parent.projectName,
                        children: siblings
                    }
                ]
            } else {
                // 没找到父节点，就降级展示原始树
                state.projectTreeDate = tree
            }

            return true
        })
    }

    function findNodeById(tree, targetId) {
        for (const node of tree) {
            if (node.projectId === targetId) return node // 找到目标节点

            if (node.children && node.children.length) {
                const found = findNodeById(node.children, targetId)
                if (found) return found
            }
        }
        return null
    }

    // 选择变化
    const onSelectChange = keys => {
        state.selectedRowKeys = keys
    }
    const getCheckboxProps = record => {
        return {
            disabled: record.stroyId
        }
    }

    function getTarget() {
        post('/solution-ppm/api/v2/built-in-system-ppm/pmgf/get/monthlyGoals', {
            targetMonthList: [state.modalForm.monthlyGoalTargetMonth, state.modalForm.monthlyGoalTargetMonth],
            projectId: props.useProjectId
        }).then(data => {
            if (data.code !== 200) {
                message.error(data.message)
                return
            }
            const allSubGoals = []

            data.data.monthlyGoalManagementDtoList?.forEach(item => {
                item.monthlyGoalTaskDtoList?.forEach(sub => {
                    allSubGoals.push({
                        label: sub.projectMonthlyGoal,
                        value: sub.id
                    })
                })
            })
            state.targetList = allSubGoals
        })
    }

    const storyFormRef = ref(null)
    const storyRules = {
        storyName: [
            {
                required: true,
                message: '请输入用户故事名称',
                trigger: 'blur'
            }
        ],
        allTime: [{ required: false, message: '请选择计划起止时间!', trigger: 'blur' }],
        projectId: [{ required: true, message: '请选择迭代项目', trigger: 'blur' }],
        ownerList: [{ required: true, message: '请选择负责人!', trigger: 'blur' }]
    }
    const currentStoryData = ref({})

    function cancelStory() {
        currentStoryData.value = {}
        state.modalVisible = false
        state.modalForm = {
            storyName: undefined,
            iterationVersionId: undefined,
            projectId: undefined,
            priority: undefined,
            labels: undefined,
            timeRangeList: [],
            taskList: [],
            templateTaskId: [],
            monthlyGoalTargetMonth: undefined,
            projectMonthlyGoalManagementId: undefined,
            remarks: undefined
        }
        state.selectedRowKeys = []
    }

    const storyQuillEditor = ref(null)

    // 保存模板项目
    function storyConfirmMbTask() {
        storyFormRef.value.validate().then(async () => {
            state.okLoading = true
            state.modalForm.taskList.forEach(item => {
                item.startTime = item.allTime[0]
                item.endTime = item.allTime[1]
            })

            let deltaContent = undefined
            deltaContent = storyQuillEditor.value.getContents()

            const imageUploadPromises = []
            deltaContent.ops.forEach(op => {
                if (op.insert && op.insert.image && op.insert.image.startsWith('data:')) {
                    const localSrc = op.insert.image

                    // 如果是 base64 图片，上传并替换为 URL
                    const file = dataURLtoFile(localSrc, 'image.png') // 将 base64 转换为 File 对象

                    const uploadPromise = uploadFileAPI(file).then(({ data: { fullUrl } }) => {
                        // 替换 op 中的 base64 URL 为服务器返回的 URL
                        op.insert.image = fullUrl
                    })

                    imageUploadPromises.push(uploadPromise)
                }
            })

            const api = currentStoryData.value.id ? put : post
            try {
                await Promise.all(imageUploadPromises)
                api(`/solution-ppm/api/v2/built-in-system-ppm/requirement/transfer`, {
                    projectId: state.modalForm.projectId,
                    timeRangeList: state.modalForm.timeRangeList,
                    storyName: state.modalForm.storyName,
                    priority: state.modalForm.priority,
                    iterationVersionId: state.modalForm.iterationVersionId,
                    labels: state.modalForm.labels,
                    description: JSON.stringify(deltaContent),
                    monthlyGoalTargetMonth: state.modalForm.monthlyGoalTargetMonth,
                    projectMonthlyGoalManagementId: state.modalForm.projectMonthlyGoalManagementId,
                    remarks: state.modalForm.remarks,
                    requirementListId: state.selectedRowKeys,
                    ownerList: state.modalForm.ownerList
                })
                    .then(data => {
                        if (data.code !== 200) {
                            message.error(data.message)
                            return
                        }
                        message.success(data.message)

                        cancelStory()

                        getData()
                    })
                    .finally(() => {
                        state.okLoading = false
                    })
            } catch (error) {
                state.okLoading = false
                console.error('图片上传失败', error)
                return // 终止提交
            }
        })
    }

    //   格式化文本展示
    import { QuillDeltaToHtmlConverter } from 'quill-delta-to-html'

    function getHtmlContent(input) {
        if (!input) return ''
        let deltaObj = null
        try {
            const parsed = typeof input === 'string' ? JSON.parse(input) : input
            if (parsed?.ops && Array.isArray(parsed.ops)) {
                deltaObj = parsed
            }
        } catch (e) {}

        if (deltaObj) {
            try {
                const converter = new QuillDeltaToHtmlConverter(deltaObj.ops, {
                    inlineStyles: false
                })
                let html = converter.convert()

                // 预览支持：用原生 <img> 包裹在一个带点击预览功能的 <a> 中
                html = html.replace(/<img[^>]*src="([^"]+)"[^>]*>/g, (match, src) => {
                    return `<img src="${src}" class="previewable-image" title="点击查看图片"/>`
                })

                return html
            } catch (err) {
                console.error('富文本转HTML失败', err)
                return ''
            }
        }

        return String(input).replace(/\n/g, '<br/>')
    }

    const currentDescription = ref({})

    function showDescription(record) {
        state.descriptionVisible = true
        currentDescription.value = record
        nextTick(() => {
            const editor = descriptionQuillEditor.value
            const content = record.description

            let delta

            // 尝试解析成 JSON
            if (typeof content === 'string') {
                try {
                    const parsed = JSON.parse(content)
                    // 判断是不是合法的 Delta 格式
                    if (parsed && typeof parsed === 'object' && Array.isArray(parsed.ops)) {
                        delta = parsed
                    }
                } catch (e) {
                    // 不是 JSON，继续走后面的纯文本逻辑
                }
            }

            if (delta) {
                // 是合法 Delta，直接设置
                editor.setContents(delta)
            } else {
                // 清空编辑器内容，插入纯文本
                editor.setText(typeof content === 'string' ? content : String(content || ''))
            }
        })
    }

    const descriptionQuillEditor = ref(null)

    async function handleSubmitDescription() {
        state.descriptionLoading = true
        let deltaContent = undefined
        deltaContent = descriptionQuillEditor.value.getContents()

        const imageUploadPromises = []
        deltaContent.ops.forEach(op => {
            if (op.insert && op.insert.image && op.insert.image.startsWith('data:')) {
                const localSrc = op.insert.image

                // 如果是 base64 图片，上传并替换为 URL
                const file = dataURLtoFile(localSrc, 'image.png') // 将 base64 转换为 File 对象

                const uploadPromise = uploadFileAPI(file).then(({ data: { fullUrl } }) => {
                    // 替换 op 中的 base64 URL 为服务器返回的 URL
                    op.insert.image = fullUrl
                })

                imageUploadPromises.push(uploadPromise)
            }
        })

        try {
            await Promise.all(imageUploadPromises)
            put(`/solution-ppm/api/v2/built-in-system-ppm/requirement/description`, {
                description: JSON.stringify(deltaContent),
                requirementId: currentDescription.value.requirementId
            })
                .then(data => {
                    if (data.code !== 200) {
                        message.error(data.message)
                        return
                    }
                    message.success(data.message)

                    cancelDescription()

                    getData()
                })
                .finally(() => {
                    state.descriptionLoading = false
                })
        } catch (error) {
            state.descriptionLoading = false
            console.error('图片上传失败', error)
            return // 终止提交
        }
    }

    function cancelDescription() {
        state.descriptionVisible = false
        currentDescription.value = {}
    }

    // 跳转到用户故事
    function jumpTask(key, projectId, storyId) {
        const isLocal = window.location.host.includes('localhost')
        let pagekey = isLocal ? 'xinpingtai' : '50001252'
        window.open(
            `${
                import.meta.env.VITE_PUBLIC_PATH
            }/page/${pagekey}?projectId=${projectId}&storyId=${storyId}&jump=true&tabKey=${key}`,
            '_blank'
        )
    }

    function getBgc(type) {
        if (type === 'P0') {
            return '#FF4D4F'
        } else if (type === 'P1') {
            return '#FF7A45'
        } else if (type === 'P2') {
            return '#FFA940'
        } else if (type === 'P3') {
            return '#FFC53D'
        }
    }

    const colorMap = {
        '进行中': '#3875FF',
        '审批中': '#1890FF',
        '未启动': '#BBBBBB',
        '完成': '#52C41A',
        '延期完成': '#FA8C16',
        '测试中': '#A0D911',
        '延期': '#FA3D16',
        '提测': '#A0D911',
        '验收': '#9254DE'
    }

    function getStatusColor(status) {
        return colorMap[status] || '#9DBAFF'
    }

    const downloadLoading = ref(false)

    function downTemplate({ url, name }) {
        downloadLoading.value = true
        get('/solution-ppm/api/v2/built-in-system-ppm/requirement/template/download', null, {
            responseType: 'blob',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            }
        })
            .then(res => {
                downloadExcel(res, '需求导入模板.xlsx')
            })
            .finally(() => {
                downloadLoading.value = false
            })
    }

    function downloadExcel(response, name) {
        const blob = new Blob([response], {
            type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
        })
        const downloadElement = document.createElement('a')
        const href = window.URL.createObjectURL(blob) // 创建下载的链接
        downloadElement.href = href
        downloadElement.download = name // 下载后文件名
        document.body.appendChild(downloadElement)
        downloadElement.click() // 点击下载
        document.body.removeChild(downloadElement) // 下载完成移除元素
        window.URL.revokeObjectURL(href)
        return href
    }

    function handlerUpload(file) {
        return new Promise((resolve, reject) => {
            if (!/\.xlsx?$/.test(file.name.toLowerCase())) {
                message.error('只能上传 xlsx 或 xls 文件')
                reject() // 必须 reject
                return
            }

            const formData = new FormData()
            formData.append('file', file)

            post(`/solution-ppm/api/v2/built-in-system-ppm/requirement/import/${props.useProjectId}`, formData)
                .then(res => {
                    if (res.code === 200) {
                        message.success('上传成功')
                        getPermissionData()
                        resolve() // 通知 uploader：成功
                        getData()
                    } else {
                        message.error(res.message || '上传失败')
                        reject() // 告诉 uploader：失败
                    }
                })
                .catch(() => {
                    reject() // catch 必须 reject
                })
        })
    }

    const currentCorrelationData = ref({})

    function showCorrelation(record) {
        getProjectTreeList()
        currentCorrelationData.value = cloneDeep(record)
        state.correlationVisible = true
    }

    // 获取用户故事
    function getStory() {
        post('/solution-ppm/api/v2/built-in-system-ppm/project/story/search', {
            projectId: state.correlationForm.projectId
        }).then(data => {
            state.storyList = data.data.map(item => {
                return {
                    label: item.storyName,
                    value: item.id,
                    priority: item.priority
                }
            })
        })
    }

    function cancelCorrelation() {
        state.correlationVisible = false
        currentCorrelationData.value = {}
        state.correlationForm = {
            projectId: undefined,
            storyId: undefined
        }
    }

    const correlationRef = ref(null)

    function handleSubmitCorrelation() {
        correlationRef.value.validate().then(() => {
            state.correlationLoading = true
            post(
                `/solution-ppm/api/v2/built-in-system-ppm/requirement/association_story/${currentCorrelationData.value.requirementId}/${state.correlationForm.storyId}`
            )
                .then(data => {
                    if (data.code === 200) {
                        message.success(data.message)
                        cancelCorrelation()
                        getData()
                    } else {
                        message.error(data.message)
                    }
                })
                .finally(() => {
                    state.correlationLoading = false
                })
        })
    }
</script>
<style lang="less" scoped>
    .page_root {
        width: 100%;
        height: 100%;
        overflow: auto;
    }

    .page_root :deep(.@{ant-prefix}-spin-nested-loading),
    .page_root :deep(.@{ant-prefix}-spin-container) {
        height: 100%;
    }

    .page_root :deep(.@{ant-prefix}-spin-container .@{ant-prefix}-table-wrapper) {
        display: flex;
        flex-flow: column nowrap;
        justify-content: flex-start;
    }

    .page_root :deep(.@{ant-prefix}-table) {
        flex: auto;
        overflow: auto;
    }

    .table-moreBtn_down {
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
        width: 100px;
    }

    .table-moreBtn_menu :deep(.table-moreBtn_menu-item):hover {
        background: #ebf1ff;
    }

    /*  表格树结构样式处理，展开按钮层级增加*/
    :deep(.@{ant-prefix}-table-row-expand-icon) {
        z-index: 1;
    }

    /*  表格树结构 由于每个表格项采用自定义组件，使用绝对定位布局，开启树结构导致显示异常，暂时使用层级定位位置 */
    :deep(.@{ant-prefix}-table-row-level-1 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 15px !important;
        width: calc(100% - 15px);
    }

    :deep(.@{ant-prefix}-table-row-level-2 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 30px !important;
        width: calc(100% - 30px);
    }

    :deep(.@{ant-prefix}-table-row-level-3 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 45px !important;
        width: calc(100% - 45px);
    }

    :deep(.@{ant-prefix}-table-row-level-4 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 60px !important;
        width: calc(100% - 60px);
    }

    /* 穿梭框改变默认样式，为根据组件样式控制左右栏宽度。 */
    :deep(.@{ant-prefix}-transfer-list) {
        height: 100%;
        width: 50%;
    }

    /*样式*/
    .top-search {
        background-color: #fff;
    }

    .top-search :deep(.ant3-col) {
        height: 40px;
    }

    .top-tip {
        font-size: 12px;
        letter-spacing: 0;
        text-align: justify;
        font-weight: 400;
        color: #ff8022;
        background: rgb(250 100 0 / 5%);
        padding: 6px;
    }

    .table-top {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-top: 8px;
        margin-bottom: 12px;
    }

    .top-right {
        display: flex;
        gap: 16px;
        flex: 1;
        justify-content: end;
    }

    .table-box :deep(.@{ant-prefix}-table-tbody) tr > td {
        font-size: 14px;
        font-weight: 400;
        color: #262626;
        border-bottom: 1px solid #d9d9d9;
        padding: 8px 16px;
        word-break: break-all;
    }

    .form-model :deep(.ant3-form-item-label) {
        width: 110px;
    }

    :deep(.ql-toolbar) {
        background: #fafafa;
        border: 1px solid #d9d9d9;
    }

    :deep(.ql-editor) {
        min-height: 110px;
        background: #ffffff;
    }

    .description :deep (.ql-editor) {
        min-height: 110px;
        background: #ffffff;
    }

    .priority-tag {
        font-style: oblique;
        background: #ccc;
        border-radius: 0;
        font-size: 14px;
        color: #ffffff;
        letter-spacing: 0;
        line-height: 22px;
        font-weight: 500;
        height: 22px;
        text-align: center;
        padding: 0 8px; /* 可根据内容调整内边距 */

        /* 自动根据内容撑开宽度 */
        display: inline-flex;
        justify-content: center;
        align-items: center;
    }

    .status-tag {
        font-size: 14px;
        color: #ffffff;
        letter-spacing: 0;
        text-align: center;
        line-height: 22px;
        font-weight: 500;
        width: 55px;
        height: 22px;
        border-radius: 2px;
        flex: 1;
    }

    .edit-approve {
        box-shadow: rgb(193, 205, 223) 0px 2px 6px;
        text-align: right;
        display: flex;
    }
</style>
